﻿using System;
using System.Collections.Generic;
using System.Linq;
using UMC.Web;
using UMC.Net;
using UMC.Data.Entities;
using UMC.ITME.Entities;
using System.IO;
using UMC.Data;

namespace UMC.ITME.Activities
{
    [Apiumc("ITME", "App", Auth = WebAuthType.Guest)]
    public class SiteAppActivity : UMC.Web.WebActivity
    {
        public override void ProcessActivity(WebRequest request, WebResponse response)
        {
            var home = WebServlet.MainDomain;
            var union = WebServlet.DomainUnion;// ".";
            var aut = request.Url.Authority;
            var host = request.Url.Host;
            if (host.EndsWith(home) && host.Length < aut.Length)
            {
                home = $"{home}{aut.Substring(host.Length)}";
            }
            var Key = this.AsyncDialog("Key", g =>
            {
                var auth = String.Empty;
                var type = this.AsyncDialog("Type", gt =>
                {
                    var uA = request.UserAgent;
                    if (uA.Contains("DingTalk"u8, true))
                    {
                        if (uA.Contains("Windows NT"u8, true) || uA.Contains("Mac OS X"u8, true))
                        {
                            return this.DialogValue("Auth");
                        }
                    }
                    return this.DialogValue("ALL");

                });
                switch (type)
                {
                    case "Auth":
                        var seesionKey = Utility.MD5(this.Context.Token.Device.Value);

                        var sesion = UMC.Data.DataFactory.Instance().Session(this.Context.Token.Device.ToString());

                        if (sesion != null)
                        {
                            sesion.SessionKey = new StringValue(seesionKey);
                            UMC.Data.DataFactory.Instance().Put(sesion);
                        }
                        auth = $"/UMC.Auth/{seesionKey}";
                        break;
                }

                var sts = new System.Data.DataTable();
                sts.Columns.Add("title");
                sts.Columns.Add("root");
                sts.Columns.Add("url");
                sts.Columns.Add("src");
                sts.Columns.Add("target");
                sts.Columns.Add("badge");
                sts.Columns.Add("desktop", typeof(bool));
                sts.Columns.Add("group");

                var group = new Dictionary<int, List<WebMeta>>();

                var user = this.Context.Token.Identity();

                UMC.Data.Session<UMC.Web.WebMeta> session = new Data.Session<WebMeta>($"{user.Id}_Desktop");

                var desktop = session.Value ?? new WebMeta();

                if (request.IsMaster)
                {

                    sts.Rows.Add("设置", "Settings", "/Setting/",
                      "/css/images/icon/prefapp.png", "max", "", true);

                    sts.Rows.Add("应用管理", "Market", "/Apps",
                   "/css/images/icon/appmgr.png", "max", "", true);

                    sts.Rows.Add("发布应用", "Market", "/Apps?Create",
                   "/css/images/icon/add.png", "max", "", true, "应用管理");

                }
                sts.Rows.Add("我的设备", "WebSSH", "/WebSSH",
               "/css/images/icon/computer.png", "max", "", request.IsMaster || desktop.ContainsKey("WebSSH"));


                var keys = new Set<StringValue>((x, y) => x.Span.SequenceCompareTo(y.Span));
                var groupKeys = new Set<StringValue>((x, y) => x.Span.SequenceCompareTo(y.Span));
                groupKeys.Put(new StringValue("Site/Group/0"));

                var pings = new HashSet<String>();
                var sites = DataFactory.Instance().Site().Where(r => r.Flag != -1).Where(r => (r.IsModule ?? false) == false)
                .OrderBy((arg) => arg.Seq ?? 1000).ToList();

                Utility.Each(sites, r =>
                {
                    keys.Put(new StringValue($"Desktop/{r.Root}"));
                    groupKeys.Put(new StringValue($"Site/Group/{r.GroupKey ?? 0}"));
                });


                var groupAuths = UMC.Security.AuthManager.IsAuthorization(user, 0, groupKeys.Span.ToArray());
                var auths = UMC.Security.AuthManager.IsAuthorization(user, 0, keys.Span.ToArray());

                var webr = UMC.Data.WebResource.Instance();
                Site[] ds;
                switch (request.SendValues?.Get("field") ?? String.Empty)
                {
                    case "root":
                        ds = (String.Equals(request.SendValues?.Get("sort"), "desc") ? sites.OrderByDescending(s => s.Root) : sites.OrderBy(s => s.Root)).ToArray();
                        break;
                    case "title":
                        ds = (String.Equals(request.SendValues?.Get("sort"), "desc") ? sites.OrderByDescending(s => s.Caption) : sites.OrderBy(s => s.Caption)).ToArray();
                        break;
                    case "auth":
                        ds = (String.Equals(request.SendValues?.Get("sort"), "desc") ? sites.OrderByDescending(s => s.AuthType) : sites.OrderBy(s => s.AuthType)).ToArray();
                        break;
                    default:
                        ds = sites.ToArray();
                        break;
                }
                foreach (var d in ds)
                {
                    if (auths[keys.IndexOf(new StringValue($"Desktop/{d.Root}"))].Item1)
                    {
                        var strUrl = $"{request.Url.Scheme}://{d.Root}{union}{home}{auth}/UMC.For/{request.Server}";

                        var title = (d.Caption ?? "App").Trim();

                        var badge = "";

                        var target = "_blank";
                        switch (d.OpenModel ?? 0)
                        {
                            case 1:
                                target = "normal";
                                break;
                            case 2:
                                target = "max";
                                break;
                        }
                        if ((d.OpenModel ?? 0) == 3)
                        {
                            strUrl = new Uri(new Uri(SiteConfig.Config(d.Domain)[0]), d.Home ?? "/").AbsoluteUri;
                        }
                        else
                        {
                            var authCnf = SiteConfig.Config(d.AuthConf);
                            if (authCnf.Contains("#") && String.IsNullOrEmpty(d.Home) == false)
                            {
                                if (d.Home.StartsWith("/Desktop/"))
                                {
                                    strUrl = d.Home;
                                }
                                else
                                {
                                    if (String.IsNullOrEmpty(d.Home) == false)
                                    {
                                        if (d.Home.StartsWith("http://") || d.Home.StartsWith("https://"))
                                        {
                                            strUrl = d.Home;
                                        }
                                        else
                                        {
                                            strUrl = $"{request.Url.Scheme}://{d.Root}{union}{home}{d.Home}";
                                        }
                                    }
                                    else
                                    {
                                        strUrl = $"{request.Url.Scheme}://{d.Root}{union}{home}{d.Home}";
                                    }
                                }
                            }
                            else if (authCnf.Contains("*"))
                            {
                                if (String.IsNullOrEmpty(d.Home) == false)
                                {
                                    if (d.Home.StartsWith("http://") || d.Home.StartsWith("https://"))
                                    {
                                        strUrl = d.Home;
                                    }
                                    else
                                    {
                                        strUrl = $"{request.Url.Scheme}://{d.Root}{union}{home}{d.Home}";
                                    }
                                }
                                else
                                {
                                    strUrl = $"{request.Url.Scheme}://{d.Root}{union}{home}{d.Home}";
                                }
                            }
                        }
                        var isDesktop = desktop.ContainsKey(d.Root);
                        if (d.IsDesktop == true)
                        {
                            if (String.Equals("hide", desktop[d.Root]))
                            {
                                isDesktop = false;
                            }
                            else
                            {
                                isDesktop = true;
                            }
                        }
                        var IsAuth = false;
                        switch (d.AuthType ?? Web.WebAuthType.User)
                        {
                            case Web.WebAuthType.Admin:
                                if (user.IsInRole(UMC.Security.Membership.AdminRole))
                                {
                                    IsAuth = true;
                                }
                                else if (UMC.Data.DataFactory.Instance().Roles(user.Id.Value, d.SiteKey.Value).Contains(UMC.Security.Membership.AdminRole))
                                {
                                    IsAuth = true;
                                }
                                break;
                            default:
                                IsAuth = true;
                                break;
                        }

                        if (IsAuth)
                        {
                            var groupKey = d.GroupKey ?? 0;
                            if (groupAuths[groupKeys.IndexOf(new StringValue($"Site/Group/{groupKey}"))].Item1)
                            {
                                var src = webr.ImageResolve(request.Url, d.Root, "1", 4, $"_t={d.ModifyTime}");
                                if (group.TryGetValue(groupKey, out var groups) == false)
                                {
                                    groups = new List<WebMeta>();
                                    group[groupKey] = groups;
                                }

                                var ping = Utility.Spell(title.Trim().Substring(0, 1));
                                if (String.IsNullOrEmpty(ping))
                                {
                                    ping = title.Trim().Substring(0, 1);
                                }
                                pings.Add(ping);
                                groups.Add(new WebMeta("ping", ping).Put("text", title.Trim(), "root", d.Root, "url", strUrl, "src", src, "target", target).Put("badge", badge));

                                sts.Rows.Add(title.Trim(), d.Root, strUrl, webr.ImageResolve(request.Url, d.Root, "1", 4, $"_t={d.ModifyTime}"), target, badge, isDesktop);
                            }
                        }
                    }


                }
                if (String.IsNullOrEmpty(UMC.Data.WebResource.Instance().Provider["appId"]))
                {
                    response.Redirect("System", "License", new Web.UIConfirmDialog("当前版本未注册，请完成登记注册")
                    {
                        Title = "应用注册",
                        DefaultValue = "Register"
                    }, false);//
                }
                else
                {
                    var lic = License.GetLicense("UserSession", 1000);

                    Data.Caches.ICacheSet cacheSet = UMC.Data.HotCache.Cache<UMC.Data.Entities.Session>();
                    if ((cacheSet.Count > lic.Quantity && lic.Quantity > 0) || (lic.ExpireTime > 0 && lic.ExpireTime < Utility.TimeSpan()))
                    {
                        response.Redirect("System", "License", new Web.UIConfirmDialog("会话规模超限,请保持合规.")
                        {
                            Title = "版权授权",
                            DefaultValue = "UserSession"
                        }, false);
                    }

                }
                var sgs = new List<WebMeta>();
                var siteGroups = DataFactory.Instance().SiteGroup().OrderBy(r => r.Seq ?? 0);

                foreach (var sg in siteGroups)
                {
                    // group.tr
                    if (group.TryGetValue(sg.Key.Value, out var _g))
                    {
                        group.Remove(sg.Key.Value);

                        sgs.Add(new WebMeta("text", sg.Caption).Put("icon", sg.Icon).Put("key", sg.Key).Put("value", _g));

                    }
                }
                if (group.TryGetValue(0, out var _g2))
                {
                    group.Remove(0);

                    var em = group.GetEnumerator();
                    while (em.MoveNext())
                    {
                        _g2.AddRange(em.Current.Value);
                    }

                    sgs.Insert(0, new WebMeta("text", "我的应用").Put("icon", "\uf00a").Put("key", "0").Put("value", _g2));
                }
                var menu = new List<WebMeta>();
                if (request.IsMaster)
                {
                    menu.Add(new WebMeta("icon", "\uf009").Put("text", "应用管理", "src", "/UMC/site"));
                    menu.Add(new WebMeta("icon", "\uf108").Put("text", "设备管理", "src", "/UMC/device"));
                    menu.Add(new WebMeta("icon", "\uf0e8").Put("text", "账户组织", "src", "/UMC/organize"));
                    menu.Add(new WebMeta("icon", "\uf0c0").Put("text", "角色管理", "src", "/UMC/role"));
                    menu.Add(new WebMeta("icon", "\uea04").Put("text", "日志安防", "src", "/UMC/log"));
                    menu.Add(new WebMeta("icon", "\uf16b").Put("text", "应用市场", "src", "/UMC/market"));
                    menu.Add(new WebMeta("icon", "\uf085").Put("text", "系统设置", "src", "/UMC/setting"));
                }
                else  //f0e8
                {


                    var searcher = UMC.Data.HotCache.Search<Entities.Device>();

                    var devices = searcher.Query(new Entities.Device(), false, 0, 1500, out var index);

                    var ds3 = devices.Select(r => new StringValue($"Device/{r.Id}")).ToArray();
                    var auths4 = UMC.Security.AuthManager.Authorization(user, 0, ds3);
                    var webGroup = new List<WebMeta>();
                    int i = 0;
                    foreach (var d in devices)
                    {
                        if (auths4[i].Item1 > 0)
                        {
                            var ping = Utility.Spell(d.Caption.Trim().Substring(0, 1));
                            if (String.IsNullOrEmpty(ping))
                            {
                                ping = d.Caption.Trim().Substring(0, 1);
                            }
                            pings.Add(ping);
                            switch (d.Type)
                            {
                                case DeviceType.Ssh:
                                    webGroup.Add(new WebMeta("ping", ping).Put("text", d.Caption.Trim(), "url", $"/UMC/WebSSH/{d.Id}", "src", "/css/images/icon/computer.png").Put("device", d.Type ?? DeviceType.Tcp));
                                    break;
                                default:

                                    webGroup.Add(new WebMeta("ping", ping).Put("text", d.Caption.Trim(), "root", $"{d.Id}", "src", "/css/images/icon/computer.png").Put("device", d.Type ?? DeviceType.Tcp));
                                    break;
                            }

                        }
                        i++;
                    }
                    if (webGroup.Count > 0)
                    {
                        sgs.Add(new WebMeta("text", "我的设备").Put("icon", "\uf17c").Put("key", "1").Put("value", webGroup));
                    }
                }

                this.Context.Send("Desktop", new WebMeta().Put("menu", menu).Put("pings", pings.OrderBy(r => r).ToArray()).Put("apps", sts).Put("IsMaster", request.IsMaster).Put("group", sgs), true);
                return this.DialogValue("none");
            });

            var site = DataFactory.Instance().Site(Key);

            var Model = this.AsyncDialog("Model", gkey =>
            {
                if (site == null)
                {
                    return this.DialogValue(Key);
                }

                var user = this.Context.Token.Identity();
                var isAdmin = false;
                var admins = Data.DataFactory.Instance().Users(site.SiteKey.Value, UMC.Security.Membership.AdminRole);
                if (admins.Length > 0)
                {
                    foreach (var v in admins)
                    {
                        if (isAdmin == false)
                        {
                            isAdmin = v.Id == user.Id;
                        }
                    }

                }
                var sheet = new UISheetDialog() { Title = "关于应用" };

                sheet.Put(new UIClick(request, gkey, "Delete") { Text = "移除账户" })
                .Put(new UIClick(request, gkey, "Account") { Text = "新增账户" });
                var siteGroup = DataFactory.Instance().SiteGroup(site.GroupKey ?? 0);
                if (request.IsMaster || isAdmin)
                {
                    sheet.Put(new UIClick(request.Model, "Site", new WebMeta("Key", site.Root, "Model", "GroupKey")) { Text = "设置分组" });
                    sheet.Put(new UIClick(request.Model, "Site", site.Root) { Text = "应用配置" });

                }
                return sheet;
            });
            switch (Model)
            {
                case "Docs":

                    this.Context.Send("Desktop.Open", new WebMeta("title", "帮助文档", "id", "Docs", "text", "帮助文档")
                        .Put("src", "/Docs").Put("max", true), true);
                    break;
                case "Settings":
                    this.AsyncDialog(Model, r =>
                    {
                        var sheet = new UISheetDialog()
                        .Put(new UIClick("System", "License", "UserSession") { Text = "许可证书" })
                        .Put(new UIClick("System", "Cache") { Text = "高速存储" })
                        .Put(new UIClick("System", "Config", "account") { Text = "账户配置" });
                        return sheet;
                    });
                    break;
                case "Market":
                    response.Redirect("ITME", "Builder");
                    break;
                case "WebSSH":
                    response.Redirect("System", "License", "WebSSH");
                    break;
                case "BgSrc":
                    {
                        var media_id = this.AsyncDialog("media_id", "none");
                        if (media_id.StartsWith("/TEMP/"))
                        {
                            string filename = UMC.Data.Reflection.ConfigPath(String.Format("Static{0}", media_id));
                            if (System.IO.File.Exists(filename))
                            {
                                var bgSrc = String.Format("/UserResources/BgSrc{0}", media_id.Substring(5));
                                using (System.IO.Stream sWriter = File.OpenRead(filename))
                                {
                                    UMC.Data.Utility.Copy(sWriter, UMC.Data.Reflection.ConfigPath($"Static{bgSrc}"));
                                    sWriter.Close();
                                }

                                var user = this.Context.Token.Identity();
                                UMC.Data.Session<UMC.Web.WebMeta> session = new Data.Session<WebMeta>($"{user.Id}_Desktop");
                                var value = session.Value ?? new WebMeta();
                                value.Put("BgSrc", bgSrc);
                                // session.ContentType = new StringValue("Settings");
                                session.Commit(value, user.Id.Value, new StringValue("Settings"), true, request.UserHostAddress);

                                this.Context.Send("BgSrc", new WebMeta().Put("src", bgSrc), true);

                                response.Redirect(request.Model, request.Command, new WebMeta().Put("Key", "LoginBgSrc", "BgSrc", bgSrc), true);


                            }
                        }
                    }
                    break;
                case "PlusDesktop":
                    {
                        var user = this.Context.Token.Identity();
                        UMC.Data.Session<UMC.Web.WebMeta> session = new Data.Session<WebMeta>($"{user.Id}_Desktop");
                        var value = session.Value ?? new WebMeta();
                        value.Put(Key, true);
                        // session.ContentType = "Settings";
                        session.Commit(value, user.Id.Value, new StringValue("Settings"), true, request.UserHostAddress);
                        response.Redirect(new WebMeta().Put("Desktop", true));
                    }
                    break;
                case "RemoveDesktop":
                    {
                        var user = this.Context.Token.Identity();
                        UMC.Data.Session<UMC.Web.WebMeta> session = new Data.Session<WebMeta>($"{user.Id}_Desktop");
                        var value = session.Value ?? new WebMeta();
                        if (site?.IsDesktop == true)
                        {
                            value.Put(Key, "hide");
                        }
                        else
                        {
                            value.Remove(Key);

                        }
                        // session.ContentType = "Settings";
                        session.Commit(value, user.Id.Value, new StringValue("Settings"), true, request.UserHostAddress);
                        response.Redirect(new WebMeta().Put("Desktop", true));
                    }

                    break;
                case "Account":
                    {
                        var user = this.Context.Token.Identity();
                        switch (site.UserModel ?? UserModel.Standard)
                        {
                            case UserModel.Check:
                            default:
                            case UserModel.Checked:
                            case UserModel.Standard:
                                break;
                            case UserModel.Bridge:
                                this.Prompt("此应用不支持设置多账户");
                                break;
                        }

                        var scookies = DataFactory.Instance().Cookies(site.Root, user.Id.Value).OrderBy(r => r.IndexValue).ToList();
                        var login = UMC.Data.Utility.TimeID();

                        var vt = login;
                        foreach (var sc in scookies)
                        {
                            if (String.IsNullOrEmpty(sc.Account))
                            {
                                login = sc.IndexValue ?? 0;
                                break;
                            }
                        }
                        if (login <= 0)
                        {
                            this.Prompt("请先设置自己主账户");
                        }
                        else
                        {
                            if (vt == login)
                            {
                                DataFactory.Instance().Put(new Entities.Cookie() { IndexValue = login, user_id = user.Id, Domain = site.Root });
                            }

                            this.Context.Send("Desktop.Open", new WebMeta("title", site.Caption, "id", site.Root, "text", "多账户对接")
                                .Put("src", $"{request.Url.Scheme}://{site.Root}{union}{home}/UMC.Login/New").Put("max", true), true);
                        }
                    }
                    break;
                case "DelPwd":
                    UMC.Data.DataFactory.Instance().Delete(new Password { Key = SiteConfig.MD5Key(site.Root, this.Context.Token.UserId.Value.ToString(), "0") });

                    break;
                case "Delete":
                    {
                        var ls = DataFactory.Instance().Cookies(site.Root, this.Context.Token.UserId.Value)
                            .Where(r => String.IsNullOrEmpty(r.Account) == false).ToArray();
                        if (ls.Length == 0)
                        {
                            this.Prompt("还未绑定账户，不需要移除");
                        }
                        var indexValue = UMC.Data.Utility.IntParse(this.AsyncDialog("IndexValue", k =>
                        {
                            if (ls.Length == 1)
                            {
                                return new UIConfirmDialog("您确认移除此应用的绑定吗") { DefaultValue = (ls[0].IndexValue ?? 0).ToString() };
                            }
                            else
                            {
                                var dc = new UISheetDialog() { Title = "请选择移除账户" };
                                foreach (var c in ls)
                                {
                                    if (String.IsNullOrEmpty(c.Account) == false && c.IndexValue != 0)
                                    {
                                        dc.Put(c.Account, c.IndexValue.ToString());
                                    }
                                }
                                return dc;
                            }
                        }), 0);
                        UMC.Data.DataFactory.Instance().Delete(new Password { Key = SiteConfig.MD5Key(site.Root, this.Context.Token.UserId.Value.ToString(), indexValue.ToString()) });
                        DataFactory.Instance().Delete(new Cookie { user_id = this.Context.Token.UserId.Value, Domain = site.Root, IndexValue = indexValue });

                        this.Prompt(String.Format("解除账户绑定成功", site.Caption));
                    }
                    break;
                case "Setting":
                    if (site != null)
                    {
                        if (request.IsMaster == false)
                        {
                            var rols = UMC.Data.DataFactory.Instance().Roles(this.Context.Token.UserId.Value, site.SiteKey.Value);
                            if (rols.Contains(UMC.Security.Membership.AdminRole) == false)
                            {
                                this.Prompt("应用管理的需要应用管理员权限");
                            }

                        }
                        this.Context.Send("Desktop.Open", new WebMeta("title", site.Caption + "设置", "id", site.Root, "text", "应用账户")
                            .Put("src", $"/Setting/{site.SiteKey.Value}").Put("max", true), true);
                    }
                    break;
                case "Password":
                    {
                        var ls = DataFactory.Instance().Cookies(site.Root, this.Context.Token.UserId.Value)
                               .Where(r => String.IsNullOrEmpty(r.Account) == false).ToArray();
                        if (ls.Length == 0)
                        {
                            this.Prompt("您未对接此应用");
                        }

                        var indexValue = UMC.Data.Utility.IntParse(this.AsyncDialog("IndexValue", k =>
                        {
                            var dc = new UISheetDialog() { Title = "请选择账户" };
                            foreach (var c in ls)
                            {
                                if (String.IsNullOrEmpty(c.Account) == false)
                                {
                                    dc.Put(c.Account, c.IndexValue.ToString());
                                }
                            }
                            if (dc.Count < 2)
                            {
                                return this.DialogValue(ls[0].IndexValue.ToString());
                            }
                            return dc;
                        }), 0);
                        var cookie = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(site.Root, this.Context.Token.UserId.Value.ToString(), indexValue.ToString()));
                        if (String.IsNullOrEmpty(cookie) == false)
                        {
                            this.Context.Send("Clipboard", new WebMeta().Put("text", cookie), true);
                        }
                        else
                        {
                            this.Prompt("您未对接此应用");
                        }
                    }
                    break;
            }
        }

    }
}